package com.zlm.zy.zhoujuanjuan.a;

import android.text.TextUtils;
import android.util.Log;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 * 创建时间: 2018/09/05 14:15
 * 作者: zhoujuanjuan
 * 描述: RSA加密
 */
public class RSAEncrypt {

  public static final String TAG = "RSAEncrypt";

  private static RSAEncrypt mInstance;

  public static final String privateKey =
    "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL2b4rRj3odxCkvnwlvzJd7Sd6F3vXA65+LUn2P+Lfz6fZO2tBRfhl3ZtF9xsHMTiwXdxDvRAWedu+Dzh0rh2mLhP28R48NTCkW/rY7F0cTTVtvVKxcHGY+N+l0kxYgrx5+r7+UkgH/NGVwYV+cJUaEkPwxV1f7ko6yO2D0iMeZ7AgMBAAECgYBMur2mVFfkJYmOKA6OGTp1DmTdEdC2jw/xyitqUp0Xp+KTmTcMm4+LgSMuEJrgJsN2r0TPFAhmfv1dzg8s7XLrKHnq/n06imgWSyDd6hbSbmtcuVkuMsp8LKw56jwIf8XoQMwAfue8EDpHCfj6uGi8FCfjhbM6zZZTbqG3AzTAQQJBAN743vMxmhzU5z6Jq6AUhPnWZFnG1VNPlplzoHU3FR56ny9efrB7i+s85i3xzUtxQzzwp2RFEY6YnMJBZJn4uaECQQDZseChHxd7s7nsYWThaP7RHZeqv7OJhdCdao4Y5ayOHM46SjVhL0VBUE9hJ/qC6cYE2AkhfosfEdZ2XqG7/kKbAkEAlU6XlMgZR8c1VgZAO8Chzt7GceuYO+JmmTj5MKSC6tb3s3OWaD1C03IDPK7XZvZgLPWFUbqCaDc/eUDqycPpIQJBAJmK7HS4CUgmq6wdxZl3BMNZq++y5l7JEyr0TOUimWJiztIuJRg2zxISIurT180eNZyVA1usdVOksS8r78c4vqECQQCs+J1FJwNf0Ya70PKLTbDHMQQRuR1DlMw5WRyRGEWTA+++jYLHLj1SQG4wWPKaM8u/l+wiy6xqHq1loVDv07vE";

  public static final String publicKey =
    "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9m+K0Y96HcQpL58Jb8yXe0nehd71wOufi1J9j/i38+n2TtrQUX4Zd2bRfcbBzE4sF3cQ70QFnnbvg84dK4dpi4T9vEePDUwpFv62OxdHE01bb1SsXBxmPjfpdJMWIK8efq+/lJIB/zRlcGFfnCVGhJD8MVdX+5KOsjtg9IjHmewIDAQAB";

  public static RSAEncrypt getInstance() {
    if (mInstance == null) {
      mInstance = new RSAEncrypt();
    }
    return mInstance;
  }

  public RSAEncrypt() {
    genKeyPair();
  }

  /**
   * 字节数据转字符串专用集合
   */
  private static final char[] HEX_CHAR = {
    '0', '1', '2', '3', '4', '5', '6',
    '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  };

  /**
   * 随机生成密钥对
   */
  private void genKeyPair() {
    // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
    KeyPairGenerator keyPairGen = null;
    try {
      keyPairGen = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }
    // 初始化密钥对生成器，密钥大小为96-1024位
    keyPairGen.initialize(1024, new SecureRandom());
    // 生成一个密钥对，保存在keyPair中
    KeyPair keyPair = keyPairGen.generateKeyPair();
    // 私钥
    PrivateKey privateKey = keyPair.getPrivate();
    // 公钥
    PublicKey publicKey = keyPair.getPublic();

    Log.e(TAG, "----privateKey----" + EncodeUtils.base64Encode(privateKey.getEncoded()));
    Log.e(TAG, "----publicKey----" + EncodeUtils.base64Encode(publicKey.getEncoded()));
  }

  /**
   * 私钥加密过程
   *
   * @param privateKey 私钥
   * @param plainTextData 明文数据
   * @throws Exception 加密过程中的异常信息
   */
  public static byte[] encrypt(PrivateKey privateKey, byte[] plainTextData)
    throws Exception {
    if (privateKey == null) {
      throw new Exception("加密私钥为空, 请设置");
    }
    Cipher cipher = null;
    try {
      // 使用默认RSA
      cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.ENCRYPT_MODE, privateKey);
      byte[] output = cipher.doFinal(plainTextData);
      return output;
    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此加密算法");
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
      return null;
    } catch (InvalidKeyException e) {
      throw new Exception("加密私钥非法,请检查");
    } catch (IllegalBlockSizeException e) {
      throw new Exception("明文长度非法");
    } catch (BadPaddingException e) {
      throw new Exception("明文数据已损坏");
    }
  }

  /**
   * 公钥解密过程
   *
   * @param publicKey 公钥
   * @param cipherData 密文数据
   * @return 明文
   * @throws Exception 解密过程中的异常信息
   */
  public static byte[] decrypt(PublicKey publicKey, byte[] cipherData)
    throws Exception {
    if (publicKey == null) {
      throw new Exception("解密公钥为空, 请设置");
    }
    Cipher cipher = null;
    try {
      // 使用默认RSA
      cipher = Cipher.getInstance("RSA");
      // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
      cipher.init(Cipher.DECRYPT_MODE, publicKey);
      byte[] output = cipher.doFinal(cipherData);
      return output;
    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此解密算法");
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
      return null;
    } catch (InvalidKeyException e) {
      throw new Exception("解密公钥非法,请检查");
    } catch (IllegalBlockSizeException e) {
      throw new Exception("密文长度非法");
    } catch (BadPaddingException e) {
      throw new Exception("密文数据已损坏");
    }
  }

  /**
   * 转成十六进制
   */
  private static void byte2hex(byte b, StringBuffer buf) {
    char[] hexChars = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      'A', 'B', 'C', 'D', 'E', 'F'
    };
    int high = ((b & 0xf0) >> 4);
    int low = (b & 0x0f);
    buf.append(hexChars[high]);
    buf.append(hexChars[low]);
  }

  /**
   * 格式化MD5值
   */
  public static String toHexString(byte[] block) {
    StringBuffer buf = new StringBuffer();
    int len = block.length;
    for (int i = 0; i < len; i++) {
      byte2hex(block[i], buf);
      if (i < len - 1) {
        buf.append(":");
      }
    }
    return buf.toString();
  }

  public static String getKeyString(Key key) throws Exception {
    byte[] keyBytes = key.getEncoded();
    String s = EncodeUtils.base64Encode(keyBytes);
    return s;
  }

  public static PublicKey getPublicKey() throws Exception {
    return getPublicKey(null);
  }

  public static PublicKey getPublicKey(String pKey) throws Exception {
    if (TextUtils.isEmpty(pKey)) {
      pKey = publicKey;
    }
    byte[] keyBytes;
    keyBytes = EncodeUtils.base64Decode(pKey);

    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(keySpec);
    return publicKey;
  }

  public static PrivateKey getPrivateKey() throws Exception {
    byte[] keyBytes;
    keyBytes = EncodeUtils.base64Decode(privateKey);

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
    return privateKey;
  }
}
